/**
 * URL parser class.
 *
 * @author Andrey Anisimov <hercules@inbox.ru>
 */

class Parser {
	
	/**
	 * Empty instance.
	 */
}

/**
 * Parses url and returns its components.
 * 
 * The returned oobject will have the following properties:
 * scheme (string) protocol scheme name (i.e. http)
 * port (int) server port
 * user (string) username if presents
 * password (string) user password if presents
 * path (string) request path
 * query (string) query string
 * fragmet (string) string after the #
 * 
 * @param url (string) URL to parse.
 * @return object
 */
Parser.parse = function(url) {
	var addr = { scheme : 'http', host : '', port : '', user : '', password : '', path : '/', query : '', fragment : '' };
	// Scheme
	var i = url.indexOf('://');
	if (i != -1) {
		addr.scheme = url.slice(0, i);
		url = url.slice(i + 3);
	}
	i = url.indexOf('/');
	if (i != -1) {
		var part = url.slice(0, i);
		url = url.slice(i);
		// Username and password
		i = part.indexOf('@');
		if (i != -1) {
			var accessKeys = part.slice(0, i).split(':');
			addr.user = accessKeys[0];
			addr.password = (accessKeys[1]) ? accessKeys[1] : '';
			part = part.slice(i + 1);
		}
		// Port number
		i = part.indexOf(':');
		if (i != -1) {
			addr.port = parseInt(part.slice(i + 1));
			part = part.slice(0, i);
		}
		addr.host = part;
	}
	// Fragment
	i = url.indexOf('#');
	if (i != -1) {
		addr.fragment = url.slice(i + 1);
		url = url.slice(0, i);
	}
	// Query string
	i = url.indexOf('?');
	if (i != -1) {
		addr.query = url.slice(i + 1);
		url = url.slice(0, i);
	}
	addr.path = url;
	return addr;
};

/**
 * @public
 * @param url {String}
 * @return {Object} Query parameter map.
 */
Parser.parseQuery = function(url) {
    var params = {};
    var q = Parser.parse(url).query;
    var kv = q.split('&');
    for (var i = 0, n = kv.length; i < n; ++i) {
        var arr = kv[i].split('=');
        var key = decodeURIComponent(arr[0]).replace(/\+/g, " ");
        var value = decodeURIComponent(arr[1]).replace(/\+/g, " ");
        if (params.hasOwnProperty(key)) {
            var param = params[key];
            if (!(param instanceof Array)) {
                params[key] = [param];
            }
            params[key].push(value);
        } else {
            params[key] = value;
        }
    }
    return params;
};